package com.taoye.thread;

import java.util.ArrayList;
import java.util.List;

/**
 * 生产消费者模式
 * <p>
 * 本例子模拟从文件读入数据，A线程模拟读入文件，读入100条由B线程写入数据库
 *
 * @author : Mr.Tao
 * @version : 1.0
 * @date : 2022/4/4 10:31
 **/
public class Demo43 {
    public static void main(String[] args) throws InterruptedException {
        Demo43Service service = new Demo43Service();
        Thread t = new Demo43Provider(service);
        t.setName("生产者-A");
        Thread t2 = new Demo43Consumer(service);
        t2.setName("消费者-A");

        t.start();
        t2.start();
    }
}

class Demo43Service {
    /**
     * 模拟读入数据的容器
     */
    private List<Integer> list = new ArrayList<>();

    public List<Integer> getList() {
        return list;
    }

    public void read() {
        for (int i = 0; i < 100; i++) {
            list.add(i);
        }
    }

    public void clear() {
        list.clear();
    }
}


/**
 * 提供者线程，用于提供消费数据
 */
class Demo43Provider extends Thread {
    private Demo43Service service;

    public Demo43Provider(Demo43Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        synchronized (service) {
            try {
                while (true) {
                    //如果容器里面还有数据没有消费，则等待消费者消费
                    if (service.getList().size() > 0) {
                        System.out.println(Thread.currentThread().getName() + "开始等待消费 ");
                        service.wait();
                    } else {
                        //如果里面没有数据，则生产数据，并唤醒消费者，让消费者消费
                        System.out.println(Thread.currentThread().getName() + "开始生产数据 ");
                        service.read();
                        service.notify();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 消费者线程，模拟拿到生产者生产的数据并存到数据库
 */
class Demo43Consumer extends Thread {
    private Demo43Service service;

    public Demo43Consumer(Demo43Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        synchronized (service) {
            try {
                while (true) {
                    //如果容器里面没有可以消费的数据，则等待生产者生产
                    if (service.getList().size() == 0) {
                        System.out.println(Thread.currentThread().getName() + "开始等待生产 ");
                        service.wait();
                    } else {
                        //如果里面有数据，则模拟保存到数据库，并清空，然后让生产者继续生产数据
                        System.out.println(Thread.currentThread().getName() + "开始消费数据，一共消费：" + service.getList().size() + "条数据到数据库 ");
                        service.clear();
                        service.notify();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}